package com.strive.village.controller;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.strive.village.common.Const;
import com.strive.village.common.Result;
import com.strive.village.entity.SysMenu;
import com.strive.village.entity.SysRole;
import com.strive.village.entity.SysRoleMenu;
import com.strive.village.entity.SysUserRole;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色管理接口
 *
 * @author strivePeng
 */
@RestController
@RequestMapping("/sys/role")
public class SysRoleController extends BaseController {
    /**
     * 返回角色列表 同时实现查询功能
     */
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:role:list')")
    public Result getRoleList(String roleName) {
        Page<SysRole> pageData = sysRoleService.page(
                getPage(),
                // 是根据传入的 roleName 参数是否为空（或非空）来决定是否添加 like 查询条件
                new QueryWrapper<SysRole>().like(StrUtil.isNotBlank(roleName), "name", roleName));
        return Result.success(pageData);
    }

    /**
     * 根据ID返回角色信息
     */
    @GetMapping("/info/{roleId}")
    @PreAuthorize("hasAuthority('sys:role:list')")
    public Result getRoleInfo(@PathVariable(name = "roleId") Long roleId) {
        SysRole role = sysRoleService.getById(roleId);
        // 查找与角色相关的菜单信息
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
        List<Long> menuIds = sysRoleMenus.stream().map(p -> p.getMenuId()).collect(Collectors.toList());
        role.setMenuIds(menuIds);
        return Result.success(role);
    }

    /**
     * 保存角色信息
     */
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:role:save')")
    public Result saveRole(@RequestBody SysRole role) {
        role.setCreated(LocalDateTime.now());
        role.setStatu(Const.STATUTS_ON);
        sysRoleService.save(role);
        return Result.success("保存成功");
    }

    /**
     * 更新角色信息
     */
    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:role:update')")
    public Result updateRole(@RequestBody SysRole role) {
        role.setUpdated(LocalDateTime.now());
        sysRoleService.updateById(role);
        // 更新缓存
        sysUserService.clearUserAuthorityInfoByRoleId(role.getId());
        return Result.success("更新成功");
    }

    /**
     * 删除角色信息
     */
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('sys:role:delete')")
    @Transactional
    public Result deleteRole(@RequestBody Long[] roleIds) {
        sysRoleService.removeByIds(Arrays.asList(roleIds));

        // 更新关联表
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().in("role_id", roleIds));
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().in("role_id", roleIds));

        // 更新缓存
        Arrays.stream(roleIds).forEach(roleId -> {
            sysUserService.clearUserAuthorityInfoByRoleId(roleId);
        });

        return Result.success("删除成功");
    }

    /**
     * 分配角色权限
     */
    @PostMapping("/prem/{roleId}")
    @PreAuthorize("hasAuthority('sys:role:perm')")
    @Transactional
    public Result premRole(@PathVariable(name = "roleId") Long roleId, @RequestBody Long[] menusIds) {
        List<SysRoleMenu> roleMenus = new ArrayList<>();
        Arrays.stream(menusIds).forEach(menuId -> {
            SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setMenuId(menuId);
            roleMenu.setRoleId(roleId);
            roleMenus.add(roleMenu);
        });

        // 保存到数据库中
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
        sysRoleMenuService.saveBatch(roleMenus);
        // 删除缓存
        sysUserService.clearUserAuthorityInfoByRoleId(roleId);
        return Result.success("分配成功");
    }
}
